package com.cmc.cloud.cmclink.doc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.lock.annotation.Lock4j;
import com.cmc.cloud.cmclink.doc.constants.errorconstant.BlnoRulePbcodeErrorCodeConstants;
import com.cmc.cloud.cmclink.doc.entity.BlnoRulePbcodeDO;
import com.cmc.cloud.cmclink.doc.mapper.BlnoRulePbcodeMapper;
import com.cmc.cloud.cmclink.doc.rpcservice.PortNameTransferService;
import com.cmc.cloud.cmclink.doc.service.BlnoRulePbcodeService;
import com.cmc.cloud.cmclink.doc.vo.blnorulepbcodevo.*;
import com.cmes.framework.common.exception.util.ServiceExceptionUtil;
import com.cmes.framework.common.pojo.PageResult;
import com.cmes.framework.mybatis.core.query.LambdaQueryWrapperX;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 接货地提单号两位码 Service 实现类
 *
 * @author 招商轮船-管理员
 */
@Service
@Validated
public class BlnoRulePbcodeServiceImpl implements BlnoRulePbcodeService {

    @Resource
    private BlnoRulePbcodeMapper blnoRulePbcodeMapper;

    @Resource
    private PortNameTransferService portNameTransferService;

    @Override
    @Lock4j(name = "blnoRulePbcodeUnique", keys = {"#createReqVO.getPorCode", "#createReqVO.getPorBlnoCode"})
    public void createBlnoRulePbcode(BlnoRulePbcodeCreateReqVO createReqVO) {
        // 插入
        validateCodeExistEd(createReqVO, null);
        BlnoRulePbcodeDO blnoRulePbcode = BeanUtil.copyProperties(createReqVO, BlnoRulePbcodeDO.class);
        blnoRulePbcodeMapper.insert(blnoRulePbcode);
    }

    @Override
    @Lock4j(name = "blnoRulePbcodeUnique", keys = {"#updateReqVO.getPorCode", "#updateReqVO.getPorBlnoCode"})
    public void updateBlnoRulePbcode(BlnoRulePbcodeUpdateReqVO updateReqVO) {
        // 校验存在
        validateBlnoRulePbcodeExists(updateReqVO.getId());
        validateCodeExistEd(updateReqVO, updateReqVO.getId());
        // 更新
        BlnoRulePbcodeDO updateObj = BeanUtil.copyProperties(updateReqVO, BlnoRulePbcodeDO.class);
        blnoRulePbcodeMapper.updateById(updateObj);
    }

    @Override
    public void deleteBlnoRulePbcode(Long id) {
        // 校验存在
        validateBlnoRulePbcodeExists(id);
        // 删除
        blnoRulePbcodeMapper.deleteById(id);
    }

    private void validateBlnoRulePbcodeExists(Long id) {
        if (blnoRulePbcodeMapper.selectById(id) == null) {
            throw ServiceExceptionUtil.exception(BlnoRulePbcodeErrorCodeConstants.BLNO_RULE_PBCODE_NOT_EXISTS);
        }
    }

    private void validateCodeExistEd(BlnoRulePbcodeBaseVO vo, Long id) {
        LambdaQueryWrapperX<BlnoRulePbcodeDO> queryWrapperX = new LambdaQueryWrapperX<BlnoRulePbcodeDO>()
                .eqIfPresent(BlnoRulePbcodeDO::getPorCode, vo.getPorCode());
        if (id != null) {
            queryWrapperX.ne(BlnoRulePbcodeDO::getId, id);
        }
        if (blnoRulePbcodeMapper.selectCount(queryWrapperX) != 0L) {
            throw ServiceExceptionUtil.exception(BlnoRulePbcodeErrorCodeConstants.BLNO_RULE_PORT_CODE_EXISTED);
        }
        LambdaQueryWrapperX<BlnoRulePbcodeDO> queryWrapperX1 = new LambdaQueryWrapperX<BlnoRulePbcodeDO>()
                .eqIfPresent(BlnoRulePbcodeDO::getPorBlnoCode, vo.getPorBlnoCode());
        if (id != null) {
            queryWrapperX1.ne(BlnoRulePbcodeDO::getId, id);
        }
        if (blnoRulePbcodeMapper.selectCount(queryWrapperX1) != 0L) {
            throw ServiceExceptionUtil.exception(BlnoRulePbcodeErrorCodeConstants.BLNO_RULE_PORT_CODE_EXISTED);
        }
    }

    @Override
    public BlnoRulePbcodeDO getBlnoRulePbcode(Long id) {
        return blnoRulePbcodeMapper.selectById(id);
    }

    @Override
    public List<BlnoRulePbcodeDO> getBlnoRulePbcodeList(Collection<Long> ids) {
        return blnoRulePbcodeMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<BlnoRulePbcodeRespVO> getBlnoRulePbcodePage(BlnoRulePbcodePageReqVO reqVO) {
        LambdaQueryWrapperX<BlnoRulePbcodeDO> queryWrapperX =
                new LambdaQueryWrapperX<BlnoRulePbcodeDO>()
                        .likeIfPresent(BlnoRulePbcodeDO::getPorCode, reqVO.getKeyWord());
        if (StringUtils.isNotEmpty(reqVO.getKeyWord())) {
            List<String> porCodes = portNameTransferService.addQuery(reqVO.getKeyWord());
            if (CollectionUtil.isNotEmpty(porCodes)) {
                queryWrapperX.or().in(BlnoRulePbcodeDO::getPorCode, porCodes);
            }
        }
        PageResult<BlnoRulePbcodeDO> pageResult = blnoRulePbcodeMapper.selectPage(reqVO, queryWrapperX);
        List<BlnoRulePbcodeRespVO> voList = BeanUtil.copyToList(pageResult.getList(), BlnoRulePbcodeRespVO.class);
        voList.forEach(entity -> entity.setPortCode(entity.getPorCode()));
        if (CollectionUtil.isNotEmpty(voList)) {
            portNameTransferService.fillName(voList);
        }
        return new PageResult<>(voList, pageResult.getTotal());
    }

    @Override
    public Map<String, String> findRuleByPorCodes(List<String> porCodes) {
        Map<String, String> resultMap = new HashMap<>(16);
        if (CollectionUtil.isEmpty(porCodes)) {
            return resultMap;
        }
        LambdaQueryWrapperX<BlnoRulePbcodeDO> queryWrapperX = new LambdaQueryWrapperX<BlnoRulePbcodeDO>();
        queryWrapperX.in(BlnoRulePbcodeDO::getPorCode, porCodes);
        queryWrapperX.eq(BlnoRulePbcodeDO::getEnable, true);
        List<BlnoRulePbcodeDO> list = blnoRulePbcodeMapper.selectList(queryWrapperX);
        return list.stream().collect(Collectors.toMap(BlnoRulePbcodeDO::getPorCode, BlnoRulePbcodeDO::getPorBlnoCode));
    }
}
